export class Matrix3
{
    private Data:number[]=[];
    constructor(init?:number[])
    {
        this.Data = new Array<number>(9);
        if(init && init.length==9)
        {
            this.Data = _.clone(init);
        }
        else
        {
            this.Data[0] =1;
            this.Data[1] =0;
            this.Data[2] =0;
            this.Data[3] =0;
            this.Data[4] =1;
            this.Data[5] =0;
            this.Data[6] =0;
            this.Data[7] =0;
            this.Data[8] =1;
        }

    }
    public clone()
    {
        return new Matrix3(this.Data);
    }
	private set( n11:number, n12:number, n13:number, n21:number, n22:number, n23:number, n31:number, n32:number, n33:number )
    {
		const te = this.Data;

		te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
		te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
		te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;

		return this;
	}
    public makeTranslate(p:IFVector2)
    {
        this.Data[2] = p.x;
        this.Data[5] = p.y;
        return this;
    }
    /**
     *
     * @param angle 弧度值
     * @returns
     */
    public makeRotator(angle:number)
    {
        this.Data[0] =Math.cos(-angle);
        this.Data[1] =-Math.sin(-angle);
        this.Data[3] =Math.sin(-angle);
        this.Data[4] =Math.cos(-angle);
        return this;
    }

    public TransltePoint(p:IFVector2):IFVector2
    {
        let x =  this.Data[0]*p.x+this.Data[1]*p.y+this.Data[2];
        let y =  this.Data[3]*p.x+this.Data[4]*p.y+this.Data[5];
        return {x:x,y:y}
    }

    public multplay(b:Matrix3)
    {

        const ae = this.Data;
		const be = b.Data;
		const te = this.Data;

		const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
		const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
		const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];

		const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
		const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
		const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];

		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
		te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
		te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;

		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
		te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
		te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;

		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
		te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
		te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
        return this;
    }
    public translate( tx:number, ty:number ) {

		const te = this.Data;

		te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
		te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];

		return this;

	}
    rotate( theta:number ) {

		const c = Math.cos( theta );
		const s = Math.sin( theta );

		const te = this.Data;

		const a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
		const a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];

		te[ 0 ] = c * a11 + s * a21;
		te[ 3 ] = c * a12 + s * a22;
		te[ 6 ] = c * a13 + s * a23;

		te[ 1 ] = - s * a11 + c * a21;
		te[ 4 ] = - s * a12 + c * a22;
		te[ 7 ] = - s * a13 + c * a23;

		return this;

	}
    /**
     * 绕点p旋转theta
     * */ 
    rotateWith(p:IFVector2,theta:number )
    {
        const tran1 = new Matrix3().makeTranslate(p);
        const ratator = new Matrix3().makeRotator(theta);
        return tran1.clone().invert().multplay(ratator).multplay(tran1)
    }
    public invert()
    {

		const te = this.Data,
        n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
        n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
        n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],

        t11 = n33 * n22 - n32 * n23,
        t12 = n32 * n13 - n33 * n12,
        t13 = n23 * n12 - n22 * n13,

        det = n11 * t11 + n21 * t12 + n31 * t13;

		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );

		const detInv = 1 / det;

		te[ 0 ] = t11 * detInv;
		te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
		te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;

		te[ 3 ] = t12 * detInv;
		te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
		te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;

		te[ 6 ] = t13 * detInv;
		te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
		te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;

		return this;

	}
}
/**
 * Static 存的是，坐标和方向 合并起来就可以用一个矩阵表达
*/
export class Static
{
    transform!:Matrix3;
    // orientation方向
    orientation!:Matrix3;
    constructor( transform?:Matrix3)
    {
        if(transform)
        {
            this.transform = transform;
        }
        else
        {
            this.transform = new Matrix3();
        }
    }
    public asMatrix()
    {
        return this.transform;
    }
}

export interface SlotAssignment<T>
{
    charactor:T
    slotNumber:number;
}
